package com.demo.function.spring.webflux;

import com.alibaba.fastjson.JSON;
import com.demo.model.entity.db.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 测试webflux提供webClient
 * @author K
 */
@Slf4j
@Service
public class WebClientService {

    /**
     * WebClient方法是线程安全，所以创建单例对象就行
     */
    private final WebClient webClient = WebClient.create();

    /**
     * 使用webClient发起异步请求，使用block方式进行阻塞获取请求结果
     * @return user对象
     */
    public User asyncRequest() {
        User user = new User();
        user.setId(666L);

        Mono<User> userMono = webClient.post().uri("http://localhost:8989/modifyUser")
                .accept(MediaType.APPLICATION_JSON)
                .bodyValue(user).retrieve().bodyToMono(User.class);
        log.info("请求已发送");
        return userMono.block();
    }

    /**
     * 使用webClient测试请求异常，判断是否在调用block方法前打印log
     */
    public void asyncRequestException() {
        User user = new User();
        user.setId(666L);

        Mono<User> userMono = webClient.post().uri("http://localhost:8989/modifyUserException")
                .accept(MediaType.APPLICATION_JSON)
                .bodyValue(user).retrieve().bodyToMono(User.class);
        log.info("请求已发送");
        User block = userMono.block();
        log.info(JSON.toJSONString(block));
    }

    /**
     * 批量发送异步请求，以阻塞方式获取结果
     */
    public ImmutablePair<List<Mono<User>>, List<Mono<String>>> batchAsyncRequest() {
        List<Mono<User>> postResults = new ArrayList<>();
        List<Mono<String>> getResults = new ArrayList<>();

        int length = 10;
        for (long i = 0; i < length; i++) {
            if (i % 2 == 0) {
                User user = new User();
                user.setUserId(i);
                Mono<User> userMono = webClient.post().uri("http://localhost:8989/respBody")
                        .accept(MediaType.APPLICATION_JSON)
                        .bodyValue(user).retrieve().bodyToMono(User.class);
                postResults.add(userMono);
            } else {
                Mono<String> stringMono =
                        webClient.get().uri("http://localhost:8989/hi").retrieve().bodyToMono(String.class);

                getResults.add(stringMono);
            }
        }
        log.info("请求已发送");

        for (Mono<String> mono : getResults) {
            log.info("getResult:{}", mono.block());
        }

        for (Mono<User> mono : postResults) {
            log.info("postResult:{}", mono.block());
        }
        return ImmutablePair.of(postResults, getResults);
    }

    public User asyncSubscribe() {
        User user = new User();
        user.setId(666L);

        Mono<User> userMono = webClient.post().uri("http://localhost:8989/modifyUser")
                .accept(MediaType.APPLICATION_JSON)
                .bodyValue(user).retrieve().bodyToMono(User.class);
        log.info("请求已发送");
        userMono.subscribe(s -> log.info("请求结果：{}", JSON.toJSONString(s)));
        return user;
    }
}
